package com.yifeng.repo.base.utils.converter;

import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Created by daibing on 2020/5/29.
 */
public class SimpleJsonHelper {
    private static final Pattern CLEAR_TEXT_PATTERN = Pattern.compile("\\s*|\t|\r|\n");

    public static <T> T parseModel(String text, Class<T> clazz) {
        Map<String, Object> map = parseMap(text);
        try {
            T instance = clazz.newInstance();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                String key = field.getName();
                if ("__PARANAMER_DATA".equals(key)) {
                    continue;
                }
                Object value = map.get(key.toLowerCase());
                if (field.getType().isEnum()) {
                    for (Object enumConstant : field.getType().getEnumConstants()) {
                        if (enumConstant.toString().equals(value.toString())) {
                            field.set(instance, enumConstant);
                            break;
                        }
                    }
                } else if (field.getType().getName().equals(Integer.class.getName()) || field.getType().getName().equals("int")) {
                    field.set(instance, ((Long) value).intValue());
                } else {
                    field.set(instance, value);
                }
            }
            return instance;
        } catch (Exception e) {
            return null;
        }
    }

    public static Map<String, Object> parseMap(String text) {
        Map<String, Object> map = new LinkedHashMap<>();
        if (isBlank(text)) {
            return map;
        }
        String plain = CLEAR_TEXT_PATTERN.matcher(text).replaceAll("");
        if (isBlank(plain)) {
            return map;
        }
        int start = 0;
        int end = 0;
        int middle = plain.indexOf(":", end);
        while (middle > 0) {
            start = plain.indexOf("\"", end);
            end = plain.indexOf(",", middle);
            if (end == -1) {
                end = plain.indexOf("}", middle);
            }

            String key = plain.substring(start + 1, middle - 1);
            String value = plain.substring(middle + 1, end);
            map.put(key.toLowerCase(), parse(value));

            middle = plain.indexOf(":", end);
        }
        return map;
    }

    private static Object parse(String str) {
        if (str.startsWith("\"") && str.endsWith("\"")) {
            return str.substring(1, str.length() - 1);
        }
        return Long.valueOf(str);
    }

    public static <T> String listModel2JsonText(List<T> list) {
        if (list == null) {
            return null;
        }
        if (list.size() == 0) {
            return "[]";
        }
        StringBuilder sb = new StringBuilder("[");
        for (T t : list) {
            String text = model2JsonText(t);
            sb.append(text).append(",");
        }
        if (sb.length() > 1) {
            sb.deleteCharAt(sb.length() - 1);
        }
        sb.append("]");
        return sb.toString();
    }

    public static String model2JsonText(Object model) {
        Map<String, Object> map = new LinkedHashMap<>();
        Field[] fields = model.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                String key = field.getName();
                Object value = field.get(model);
                if ("__PARANAMER_DATA".equals(key)) {
                    continue;
                }
                if (value == null) {
                    continue;
                }
                map.put(key, value);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("parse model failed: " + field.toString());
            }
        }
        return map2JsonText(map);
    }

    public static String map2JsonText(Map<String, Object> map) {
        if (map == null) {
            return null;
        }
        if (map.size() == 0) {
            return "{}";
        }
        StringBuilder sb = new StringBuilder("{");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() != null) {
                if (entry.getValue() instanceof String || entry.getValue() instanceof Enum) {
                    sb.append("\"").append(entry.getKey()).append("\":\"").append(entry.getValue()).append("\"").append(",");
                } else {
                    sb.append("\"").append(entry.getKey()).append("\":").append(entry.getValue()).append(",");
                }
            }
        }
        if (sb.length() > 1) {
            sb.deleteCharAt(sb.length() - 1);
        }
        sb.append("}");
        return sb.toString();
    }

    private static boolean isBlank(String s) {
        return s == null || s.trim().length() == 0;
    }

    public static void main(String[] args) {
        String text = "{\n" +
                "  \"requestTime\": 1590728352520,\n" +
                "  \"traceId\": \"trace-id-00001\",\n" +
                "  \"threadName\": \"http-thread-001\",\n" +
                "  \"stage\": \"develop\",\n" +
                "  \"hostName\": \"host-name-0001\",\n" +
                "  \"responseTime\": 1590728352621,\n" +
                "  \"appId\": \"xappId1\",\n" +
                "  \"accessStage\": \"QUIT\",\n" +
                "  \"sid\": \"spinus-sid-0010\",\n" +
                "  \"takeMillis\": 100,\n" +
                "  \"responseStatus\": 200,\n" +
                "  \"url\": \"http://blog.sina.com.cn/s/blog_3fba24680102xlxc.html\"\n" +
                "}";
        Map<String, Object> map = parseMap(text);
        System.out.println("map: " + map.toString());

//        AccessLogData data = parseModel(text, AccessLogData.class);
//        System.out.println("data: " + data.toString());

    }

}
